# $Rev: 6 $
# $Author: archon810 $
# $Date: 2009-05-24 07:14:36 +0000 (Sun, 24 May 2009) $
# $HeadURL: http://wp-copy-tool.googlecode.com/svn/trunk/Utils.pm $
#
#  WP Copy Tool - http://beerpla.net
#  Copyright (C) 2009 Artem Russakovskii
#
#  == BEGIN LICENSE ==
#
#  Licensed under the terms of GNU General Public License Version 2 or later (the "GPL")
#     http://www.gnu.org/licenses/gpl.html
#
#  == END LICENSE ==
#

use strict;
use vars qw(%settings %dbh);

use Cwd;
use Data::Dumper;
use DBI;
use File::Basename;
use File::Copy;
use Getopt::Long;
use Term::ANSIColor qw(:constants);
use Socket;
use Sys::Hostname;

####################
# HELPER FUNCTIONS #
####################

# prints usage and exits
sub usage(){
	print "Usage " . basename($0) . " TODO\n";
	exit();
}

# prints the function name it was called from
# also change to the scratchpad dir
sub func_start
{
	my $function = ( caller( 1 ) )[3] if defined caller( 1 );
	$function =~ s/^main:://;
	my $output = "Starting function ". GREEN . $function . RESET . "\n";
	print "\n$output";
}

# execute a command using backticks
sub exec_cmd
{
	my ($cmd) = @_;
	print "Executing ", YELLOW, "$cmd\n", RESET;
	my $output = `$cmd`;
	print $output;
	return $output;
}

# execute a command using system()
sub system_cmd
{
	my ($cmd, $ignore_error_codes) = @_;
	my $ret_code = 1;
	foreach my $try (1..$settings{max_retries}){
		print "[[TRY $try]] Executing ", YELLOW, "$cmd\n", RESET;
		$ret_code = system($cmd);
		if($ret_code && !$ignore_error_codes){
			print "[[TRY $try]] ", RED, "Failed with return code " . ($ret_code >> 8) . "!\n", RESET;
		}
		else
		{
			print "[[TRY $try]] ", GREEN, "Success!\n", RESET;
			last;
		}
	}

	# handle errors
	if($ret_code && !$ignore_error_codes)
	{
		print RED, "$cmd failed after $settings{max_retries} attempts.\n", RESET;
		my $response = prompt("y", "Do you want to proceed?", undef, "no");
		exit if !$response;
	}

	return $ret_code;
}

# execute a command using Expect
sub expect_cmd
{
	my ($cmd) = @_;
	print "Executing ", YELLOW, "$cmd\n", RESET;

	my $exp = Expect->spawn($cmd) or print RED, "Cannot spawn Expect: $!\n" and exit;
	return $exp;
}

# a handy auto enter clicker for Expect
# sends "\n" when it detects a certain pattern
sub auto_enter
{
	my ($exp) = @_;
	$exp->expect(
		undef,
		# match anything in brackets
		[qr/\[.*?\]/ =>
				sub {
					# ignore some common known non-prompts
					if($exp->match() !~ /\[(requires|test.*|\d+)\]/i)
					{
						my $fh = shift;
						print GREEN, "\n[[AUTO-ENTER]]\n", RESET;
						$fh->send( "\n");
					}
					eval{no strict 'subs';exp_continue;use strict 'subs'};
				}
		],
	);
}

# connects to a db at a given location and sets a global with the db handle
sub db_connect
{
	my ($db_host, $db_name, $db_user, $db_passwd, $db_port, $allowed_retries) = @_;
	$allowed_retries ||= 10e10;
	my $dsn = "DBI:mysql:database=$db_name;host=$db_host;port=$db_port";

	my $msg;
	do
	{
		$allowed_retries--;
		eval{
			if(!defined $dbh{$db_name} || !$dbh{$db_name}->ping) { # check for active connection
				# auto_reconnect currently CRASHES (yeah, seg faults) the program if $dbh->ping is used after an established connection died.
				#$dbh{$db_name} = DBI->connect($dsn, $db_user, $db_passwd, {RaiseError => 1, InactiveDestroy => 1, mysql_auto_reconnect => 1}) or die "$DBI::errstr";
				$dbh{$db_name} = DBI->connect($dsn, $db_user, $db_passwd, {RaiseError => 1, InactiveDestroy => 1}) or die "$DBI::errstr";
				$msg = "[[DB CONNECT]] Successfully connected to $db_user\@$db_host $db_name.";
			}
			print "$msg\n" if defined $msg;
			# set the client to use UTF-8
			$dbh{$db_name}->do("SET NAMES 'utf8'");
		};
		if ($@)
		{
			print("[[DB ERROR]] " . ($DBI::errstr || $@) . ". Reconnecting in $settings{db_reconnect_interval} seconds.\n");
			print("[[DB RECONNECT]] $allowed_retries retries remaining.\n");
			sleep $settings{db_reconnect_interval};
		}
	} until !$@ || (defined $allowed_retries && $allowed_retries <= 0);
	return $dbh{$db_name};
}

sub is_empty
{
	!defined $_[0] || $_[0] eq ""
}

1;